package test1;

import entity.PublicVar;
import extthread.ThreadA;

/**
　* @Description: TODO
　* @param ${tags}
　* @return ${return_type}
　* @throws
　* @author Merlin
　* @date 2018/6/19 13:32
　*/

/**
 * 脏读
 * 虽然在赋值时进行了同步，但在取值时有可能出现一些意想不到的意外，这种情况就是脏读。
 * 发生脏读的情况是在读取实例变量时，此值已经被其他线程更改过了。
 */
public class Test {

	public static void main(String[] args) {
		try {
			PublicVar publicVarRef = new PublicVar();
			ThreadA thread = new ThreadA(publicVarRef);
			thread.start();
			// 打印结果受此值大小影响
			Thread.sleep(200);

			publicVarRef.getValue();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * setValue()方法同步，getValue()方法不同步。
	 * 输出结果：
	 * getValue method thread name=main username=B password=AA
	   setValue method thread name=Thread-0 username=B password=BB
	 *
	 * 可以看出因为getValue()方法并不是同步的，所以出现了脏读。解决办法，也加上同步synchronized关键字
	 *
	 * 加上后运行结果：
	 * setValue method thread name=Thread-0 username=B password=BB
	   getValue method thread name=main username=B password=BB
	 *
	 * 通过这个案例不仅要知道脏读是通过synchronized 关键字解决的，还要知道如下内容：
	 * 	 当A线程调用anyObject对象加入synchronized关键字的X方法时，A线程就获得了X方法锁，更
	 * 准确的讲，是获得了对象的锁，所以其他线程必须等A线程执行完毕才可以调用X方法，
	 * 但B线程可以随意调用其他的非synchronized同步方法
	 * 	 当A线程调用anyObject对象加入synchronized关键字的X方法时，A线程就获得了X方法锁，
	 * 所以其他线程必须等A线程执行完毕才可以调用X方法，而B线程如果调用声明了synchronized关键字的
	 * 非X方法时，必须等A线程将X方法执行完，也就是释放对象锁后才可以调用。这时A线程已经执行了一个
	 * 完成的任务，也就是说username和password这两个实例变量已经同时被赋值，不存在脏读的基本环境。
	 */
}
